package jml.defaultimple.web;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import jml.config.Config;
import jml.config.FileType;
import jml.config.FileTypes;
import jml.config.cmd.Command;
import jml.config.cmd.CommandExec;
import jml.config.cmd.CommandGroup;
import jml.def.Library;
import jml.def.Title;
import jml.defaultimple.util.JMLPluginManager;
import jml.defaultimple.util.UFile;

@WebServlet("/player")
public class ServletPlayer extends HttpServlet
{
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException
	{
		Library library = (Library) getServletContext().getAttribute("library");
		
		// recibo el path del title a tocar
		String titlePath = request.getParameter("idAlbum");
		String titlePathOK = URLDecoder.decode(titlePath, "UTF-8");
		
		Title title = library.getTitleByPath(titlePathOK);

		// recibo el comando (play o add)
		String cmd = request.getParameter("cmd");
		
		String albumFileType = _getAlbumFileType(titlePathOK);
		Config c = Config.getConfig(true);
		FileTypes ft = c.getFileTypes();
				
		Command player;
		if( albumFileType!=null )
		{
			FileType albumType = ft.getFileTypes().get(albumFileType);
			player = albumType.getPlayer();
		}
		else
		{
			player = ft.getDefaultPlayer();
		}
		
//		String param = player.getAtts().get(cmd);
		String param = player.getProps().get(cmd);

		// obtengo las carpetas (por si el disco el multiple)
		ArrayList<String> folders = _getSubfoldersFullPath(library, titlePathOK);

		// la primera carpeta la "play" o la "add" segun sea el parametro
		_procesarFolder(c.getCommandGroup(),player, param, folders.get(0));
		for(int i = 1; i < folders.size(); i++)
		{
			// de haber mas carpetas las "add"
			param = player.getProps().get("add");
			_procesarFolder(c.getCommandGroup(),player, param, folders.get(i));
		}
		
		// notifico a los plugins que se acaba de cargar un titulo
		JMLPluginManager.notifyAll("onPlay", title);	
		
		Command ss = c.getCommandGroup().getComnand("SLIDESHOW","default");
		boolean isAutoStart = !ss.getProps().get("auto-start").equals("0");
		boolean isApplySlideshow = player.getProps().get("apply-slideshow").equals("true");
		if( cmd.equals("play") && isApplySlideshow && isAutoStart )
		{
			int n=Integer.parseInt(ss.getProps().get("auto-start"));
			request.getRequestDispatcher("/slideshow?path="+titlePath+"&delay="+n).forward(request,response);
		}
		
		return;
	}

	private static void _procesarFolder(CommandGroup ec,Command player, String param, String fullFolder)
	{
		try
		{
			// retorna el fileType "cue" o "flac", etc...
			String fileType = _getAlbumFileType(fullFolder);

			if(fileType != null && !fileType.equals("cue") && !fileType.equals("m3u")&& !fileType.equals("VIDEO_TS"))
			{
				// genero el .m3u
				_makeM3UFile(fullFolder, fileType);

				fileType = "m3u";
			}

			if(fileType == null)
			{
				
//				ArrayList<String> args = new ArrayList<String>();
//				
//				args.add(ec.getRuntimeScript());
//				args.add(ec.getDefaultScript());
//				
//				args.add(player.getPath());
//				args.add("\""+param+"\"");
//				args.add("\""+x+"\"");
//				ProcessBuilder pb = new ProcessBuilder(args);
//				pb.start();
			
				String x = _reemplazarBarra(fullFolder);
				x = UFile.getShortFilename(x);
				player.getAppParams().put("TITLEPATH",x);
				player.getAppParams().put("ACTION",param);
				CommandExec.exec(player);
				
				// el primero lo toco o lo encolo segun el parametro
				//Runtime.getRuntime().exec(sExec);

				return;
			}

			// obtengo todos los files que matchean con el fileType
			File fFile = new File(fullFolder);
			String[] filesToPlay = fFile.list(new FilterByFileType(fileType));

			for(int i = 0; i < filesToPlay.length; i++)
			{

				
//				ArrayList<String> args = new ArrayList<String>();
//				
//				
//				args.add(ec.getRuntimeScript());
//				args.add(ec.getDefaultScript());
//				
//				args.add(player.getPath());
//				args.add(param);
//				args.add(UFile.getShortFilename(x));
//				ProcessBuilder pb = new ProcessBuilder(args);
//				pb.start();

				String x = _reemplazarBarra(fullFolder + "/" + filesToPlay[i]);
				x = UFile.getShortFilename(x);
				player.getAppParams().put("TITLEPATH",x);
				player.getAppParams().put("ACTION",param);
				CommandExec.exec(player);


				// demora porque el proceso se dispara asincronicamente...
				int delay = Integer.parseInt(player.getProps().get("multifolder-delay"));
				Thread.sleep(delay);
			}
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
			throw new RuntimeException(ex);
		}
	}

	private static void _makeM3UFile(String fullFolder, String fileType)
	{
		// posicion de la ultima barra
		int p = fullFolder.lastIndexOf("/");
		p = p >= 0 ? p : fullFolder.lastIndexOf("\\");

		// nombre del m3u que voy a generar
		String m3uFileName = fullFolder.substring(p + 1) + ".m3u";

		File f = new File(fullFolder);
		String[] files = f.list(new FilterByFileType(fileType));

		try
		{
			FileOutputStream fos = new FileOutputStream(fullFolder + "/" + m3uFileName);
			for(int i = 0; i < files.length; i++)
			{
				fos.write((files[i] + "\n").getBytes());
			}

			fos.close();
		}
		catch(Exception e)
		{
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

	private static String _reemplazarBarra(String x)
	{
		String barraOk = System.getProperty("file.separator");
		if(barraOk.equals("/"))
		{
			return x.replace("\\", "/");
		}
		else
		{
			return x.replace("/", "\\");
		}
	}

	private static ArrayList<String> _getSubfoldersFullPath(Library library, String path)
	{
		Title title = library.getTitleByPath(path);

		// subfolders (por si el disco el multiple)
		String subfolders[] = title.getSubfolders();

		ArrayList<String> folders = new ArrayList<String>();

		// disco simple
		if(subfolders == null || subfolders.length == 0)
		{
			folders.add(path);
		}
		else
		// disco multiple
		{
			for(String sf : subfolders)
			{
				folders.add(path + "/" + sf);
			}
		}

		return folders;
	}

	// retorna "cue", "m3u", "flac",... o null
	private static String _getAlbumFileType(String fullPath)
	{
		// los filetypes definidos en el config
		FileTypes ft = Config.getConfig(true).getFileTypes();

		// barro la carpeta...
		File f = new File(fullPath);
		String files[] = f.list();

		// recorro los types
		for(Enumeration<String> e=ft.getFileTypes().keys(); e.hasMoreElements();)
		{
			// recorro los files/dirs
			String ext = e.nextElement();
			for(int j = 0; j < files.length; j++)
			{
				if(files[j].endsWith(ext))
				{
					return ext;
				}
			}
		}

		return null;
	}

	static class FilterByFileType implements FilenameFilter
	{
		private String ext;

		public FilterByFileType(String ext)
		{
			this.ext = ext;
		}

		@Override
		public boolean accept(File dir, String name)
		{
			return name.endsWith(ext);
		}
	}

}
